package com.zlzlib.librxpermiss;

import java.util.List;

import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.functions.BiConsumer;
import io.reactivex.rxjava3.functions.Function;
import io.reactivex.rxjava3.functions.Predicate;


/**
 * @Desc:权限信息数据实体
 * @Copyright:
 * @DateTime: 2020/9/19 16:15
 * @Author zlz
 * @Version 1.0
 */
public class Permission {
    /**
     * ACCEPT_HANDOVER	PHONE(电话组)	允许呼叫应用继续在另一个应用中启动的呼叫
     * ACCESS_BACKGROUND_LOCATION	LOCATION(定位组)	允许应用程序在后台访问位置
     * ACCESS_COARSE_LOCATION	LOCATION(定位组)	允许程序通过WiFi或移动基站的方式获取用户错略的经纬度信息
     * ACCESS_FINE_LOCATION	LOCATION(定位组)	允许程序通过GPS芯片接收卫星的定位信息
     * ACTIVITY_RECOGNITION		允许应用程序识别物理活动
     * ADD_VOICEMAIL	PHONE(电话组)	允许程序添加语音邮件系统
     * ANSWER_PHONE_CALLS	PHONE(电话组)	允许程序接听来电
     * BODY_SENSORS	SENSORS(传感器组)	允许应用程序访问用户用来测量身体内部情况的传感器数据，例如心率
     * CALL_PHONE	PHONE(电话组)	允许程序从非系统拨号器里拨打电话
     * CAMERA	CAMERA(相机拍照组)	允许程序访问摄像头进行拍照
     * GET_ACCOUNTS	CONTACTS(联系人组)	允许程序访问账户Gmail列表
     * PROCESS_OUTGOING_CALLS	PHONE(电话组)	允许程序监视，修改或放弃播出电话
     * READ_CALENDAR	CALENDAR(日历组)	允许程序读取用户的日程信息
     * READ_CALL_LOG	PHONE(电话组)	允许程序读取通话记录
     * READ_CONTACTS	CONTACTS(联系人组)	允许程序访问联系人通讯录信息
     * READ_PHONE_NUMBERS	PHONE(电话组)	允许程序读取设备的电话号码
     * READ_PHONE_STATE	PHONE(电话组)	允许程序访问电话状态
     * READ_SMS	SMS(手机短信服务组)	允许程序读取短信内容
     * RECEIVE_MMS	SMS(手机短信服务组)	允许程序接收彩信
     * RECEIVE_SMS	SMS(手机短信服务组)	允许程序接收短信
     * RECEIVE_WAP_PUSH	SMS(手机短信服务组)	允许程序接收WAP PUSH信息
     * RECORD_AUDIO	MICROPHONE(麦克风组)	允许程序录制声音通过手机或耳机的麦克
     * SEND_SMS	SMS(手机短信服务组)	允许程序发送短信
     * USE_SIP	PHONE(电话组)	允许程序使用SIP视频服务
     * WRITE_CALENDAR	CALENDAR(日历组)	允许程序写入日程，但不可读取
     * WRITE_CALL_LOG	PHONE(电话组)	允许程序写入（但是不能读）用户的联系人数据
     * WRITE_CONTACTS	CONTACTS(联系人组)	允许程序写入联系人,但不可读取
     * READ_EXTERNAL_STORAGE	STORAGE(存储组)	允许程序可以读取设备外部存储空间
     * WRITE_EXTERNAL_STORAGE	STORAGE(存储组)	允许程序写入外部存储,如SD卡上写文件
     */

    //权限名称
    public final String name;
    //权限是否已经授权
    public final boolean granted;
    //是否有提示
    public final boolean shouldShowRequestPermissionRationale;

    public Permission(String name, boolean granted) {
        this(name, granted, false);
    }

    public Permission(String name, boolean granted, boolean shouldShowRequestPermissionRationale) {
        this.name = name;
        this.granted = granted;
        this.shouldShowRequestPermissionRationale = shouldShowRequestPermissionRationale;
    }

    public Permission(List<Permission> permissions) {
        //合并得到数据的值
        name = combineName(permissions);
        granted = combineGranted(permissions);
        shouldShowRequestPermissionRationale = combineShouldShowRequestPermissionRationale(permissions);
    }

    @Override
    public boolean equals(final Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        final Permission that = (Permission) o;
        if (granted != that.granted) return false;
        if (shouldShowRequestPermissionRationale != that.shouldShowRequestPermissionRationale)
            return false;
        return name.equals(that.name);
    }

    @Override
    public int hashCode() {
        int result = name.hashCode();
        result = 31 * result + (granted ? 1 : 0);
        result = 31 * result + (shouldShowRequestPermissionRationale ? 1 : 0);
        return result;
    }

    @Override
    public String toString() {
        return "Permission{" +
                "name='" + name + '\'' +
                ", granted=" + granted +
                ", shouldShowRequestPermissionRationale=" + shouldShowRequestPermissionRationale +
                '}';
    }

    private String combineName(List<Permission> permissions) {
        return Observable.fromIterable(permissions)
                .map(new Function<Permission, String>() {
                    @Override
                    public String apply(Permission permission) throws Exception {
                        return permission.name;
                    }
                }).collectInto(new StringBuilder(), new BiConsumer<StringBuilder, String>() {
                    @Override
                    public void accept(StringBuilder s, String s2) throws Exception {
                        if (s.length() == 0) {
                            s.append(s2);
                        } else {
                            s.append(", ").append(s2);
                        }
                    }
                }).blockingGet().toString();
    }

    private Boolean combineGranted(List<Permission> permissions) {
        return Observable.fromIterable(permissions)
                .all(new Predicate<Permission>() {
                    @Override
                    public boolean test(Permission permission) throws Exception {
                        return permission.granted;
                    }
                }).blockingGet();
    }

    private Boolean combineShouldShowRequestPermissionRationale(List<Permission> permissions) {
        return Observable.fromIterable(permissions)
                .any(new Predicate<Permission>() {
                    @Override
                    public boolean test(Permission permission) throws Exception {
                        return permission.shouldShowRequestPermissionRationale;
                    }
                }).blockingGet();
    }
}
